DOS CGI Scripting Background
The demo page and some examples in the documentation require
the server to run back-end scripts in a DOS window. They will
fail if you don't have enough environment space. Add a line CommandEnvSize=8192
(or whatever you need) to the
[NonWindowsApp]
section of SYSTEM.INI
.
Introduction
Needless to say, Windows has an unusual environment. If you are familiar
with Unix systems, this is going to seem baroque to you. On the other
hand, you might as well get used to multi-environment systems. Windows
NT has a micro-kernel that supports four "environment
subsystems" (DOS, POSIX, Windows-32, and OS/2) with a clever
kernel-level client-server architecture. Furthermore, Windows-32
supports both console-style and GUI applications, either of which can
start applications that run under any of the other environment
subsystems. Finally, the upcoming "Chicago" release of Windows will have
both DOS and Windows environments, just like the current version.
DOS Virtual Machines
OK, back to the present. The Windows environment has no native command
interpreter. However, a Windows application (like httpd) can create a
DOS virtual machine (VM) and make use of the services of the DOS
command interpreter. On the other hand, a DOS VM cannot start a
Windows application. Since the script runs in the DOS VM, the script is
limited to running DOS programs. Normally this is not a big deal.
Environment Variables
When a client issues a request to the server, it sends a message that
contains information needed to satisfy the request. Normally the server
uses this information directly to return the appropriate document in the
appropriate format. When the target of the client's request is a script,
the server creates a number of environment variables which
contain the information needed for the script to satisfy the client's
request. These variables, and their contents, are a core part of the
CGI/1.0 specification.
Environment variables created by a Windows application are not available
to a DOS VM started by that application. Therefore, the httpd server
must create a "jacket script" which contains the commands to define the
CGI environment variables within the DOS VM's environment before
invoking the actual script.
Standard Input and Output
There is no way for a Windows application to connect pipes to a program
running in a DOS VM. Windows Sockets socket descriptors cannot be used
in place of file descriptors (all this goes away on NT, by the way).
CGI/1.0 requires that a script be able to write its results to its
standard output, and read any content furnished by the client on its
standard input.
In order to create an environment that conforms to the CGI/1.0
specification, the Windows httpd server creates its script command line
with redirection to and from temporary files, and manages those files
automatically. The effect is to create a CGI/1.0 environment with no
special action needed by the script. Content furnished by a client as
part of a (e.g., PUT) request is placed into the tempfile that is
connected to the script's standard input. Any output generated on the
script's standard output is redirected to a tempfile that is read by
the server and transmitted back to the client.
Processing Steps
The cleanest way to start a DOS VM is to use a Windows Program
Information File (PIF). The PIF contains a variety of specifications
that will be applied to the created DOS VM.
The command interpreter
Normally, the DOS program that is initially exec'ed in the VM is a
command interpreter such as COMMAND.COM. This command interpreter is
quite limited when compared to some 3rd party
alternatives. Keep this in mind.
- NOTE:
- The output
of COMMAND.COM itself cannot be redirected, nor can the output of
any script (BAT file) invocation. This creates a nearly intolerable
situation where the output of all of the commands in a script must be
individually redirected explicitly
to the file named in the
OUTPUT_FILE environment variable,
using the ">" operator for the very first
output, and the ">>" operator thereafter. The scripts used for the
examples in the httpd online documentation are written this way. Once
you look at them, you'll want to get a
more useful shell.
An obscure feature of PIF files is that they permit DOS environment
variable substitution for the EXE path, the working directory and the
optional parameters. Any environment variables used for this purpose
must be defined in the "system VM", in other words, before Windows is
started. For example, you can use %COMSPEC%
for the EXE
file and %TEMP%
for the working directory. Note that using
an environment variable in the EXE file field of the PIF Editor will
cause an error alert to appear when you try to save the PIF file. This
is an annoyance; the file will be saved as you specified.
Starting the VM
To start the DOS VM, the httpd server execs the following command line:
hscript.pif /c hscript.bat < hscript.inp > hscript.out
hscript.pif
is the PIF that actually starts the DOS VM and
the command interpreter. Within the PIF file that is shipped with httpd,
the EXE file is %COMSPEC%
, which starts your DOS command
interpreter. The PIF working
directory is set to %TEMP%
which should be the path to your
temporary directory. These must be set properly before starting
windows.
The /c
is the command interpreter's "exec option", which
tells the interpreter to exit when the process finishes (instead of
returning to the interactive prompt). This changes to /k
if you enable script debugging, so you can see what happened in the DOS
VM before it exits.
hscript.bat
is the environment initialization "jacket
procedure" (see below) that sets the CGI environment variables in the VM
environment, then execs the client's target script.
hscript.inp
contains any PUT/POST content that came along
with the client's request (if any), and hscript.out
will
receive any output that the script places on its standard output (the redirections are useless to COMMAND.COM
).
Environment Initialization
Once the DOS VM has been started, and the command interpreter is
running, it is necessary to define the CGI environment variables within
the VM's environment. To accomplish this, the server generates a "jacket
procedure" that first defines the environment variables and then execs
the actual script that is the target of the client request. It looks
like this:
@ECHO OFF
SET SERVER_SOFTWARE=<whatever>
... <other SET statements>
c:/httpd/cgi-bin/myscript.bat myargs
The @ECHO OFF
is required to prevent the environment
variable initialization statements from appearing in the script output.
Target script execution
The last line in the jacket procedure invokes the client-specified
script for execution in the newly created environment. Any
query arguments
that appear following a "?" in the URL are put on the script command line.
Post-Processing
When the target script completes, the jacket procedure exits as well. At
this point, the server must transmit the results in the output file back
to the client. There are two variations on this:
- Normally, the server reads the script output and automatically
generates the required HTTP header for the response.
- If the target script filename begins with
nph-
, then
the server bypasses header generation and sends the contents of the
output file to the client transparently. In this case, the script is
responsible for generating the HTTP header as well as the document
content.
Once the result has been transmitted to the client, the server will
delete the temporary files.
A Note From the Author
If you read this far, thank you. This is complex stuff.
It's easy to say that Windows is a mess. In my opinion it's an example
of the "struggle stage" of a new way of doing things. You can expect
things to get more complicted because you can do more things. I love
Unix for what it is and what it has done for us all. But those "kinder,
gentler" days are passing away. Multi-environment, multi-threaded,
GUI/network based systems are here. And it can be complex. So take a
deep breath and give this stuff a try.
Once you reach Wizard level, you can try
execing other programs (such as a tcl or perl interpreter) directly. There are
ways to control the content of the environment initialization "jacket
procedure" that the server generates so that the environment variables
carrying the client request information can be defined with the
appropriate syntax. You can even control the syntax of the command line
that is fed to the PIF file. Don't try this at home.
Basic Scripting
Return to the
Scripting Overview
Robert B. Denny <rdenny@netcom.com>